package algorithm

import (
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/wcharczuk/go-chart/v2"
	"github.com/wcharczuk/go-chart/v2/drawing"
)

// ChartRenderer 图表渲染器
type ChartRenderer struct {
	outputDir string
	colors    []drawing.Color
}

// NewChartRenderer 创建图表渲染器
func NewChartRenderer(outputDir string) *ChartRenderer {
	return &ChartRenderer{
		outputDir: outputDir,
		colors: []drawing.Color{
			{R: 0, G: 128, B: 255, A: 255}, // 蓝色
			{R: 0, G: 255, B: 0, A: 255},   // 绿色
			{R: 255, G: 165, B: 0, A: 255}, // 橙色
			{R: 255, G: 0, B: 0, A: 255},   // 红色
			{R: 128, G: 0, B: 128, A: 255}, // 紫色
		},
	}
}

// saveChart 保存图表到文件
func (r *ChartRenderer) saveChart(graph interface{}, outputPath string) error {
	// 确保输出目录存在
	if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil {
		return fmt.Errorf("创建输出目录失败: %v", err)
	}

	// 创建输出文件
	f, err := os.Create(outputPath)
	if err != nil {
		return fmt.Errorf("创建输出文件失败: %v", err)
	}
	defer f.Close()

	// 根据图表类型渲染
	switch g := graph.(type) {
	case *chart.BarChart:
		return g.Render(chart.PNG, f)
	case *chart.Chart:
		return g.Render(chart.PNG, f)
	default:
		return fmt.Errorf("不支持的图表类型")
	}
}

// RenderBarChart 渲染柱状图
func (r *ChartRenderer) RenderBarChart(title string, xLabel string, yLabel string, xValues []string, yValues []float64, outputPath string) error {
	// 检查数据范围是否为零
	allZero := true
	for _, v := range yValues {
		if v > 0 {
			allZero = false
			break
		}
	}

	// 如果所有值都是零，添加一个小的偏移量以避免数据范围为零
	if allZero && len(yValues) > 0 {
		for i := range yValues {
			yValues[i] = 0.1 // 添加一个小的非零值
		}
	}

	// 创建图表
	bars := make([]chart.Value, len(xValues))
	for i := range xValues {
		bars[i] = chart.Value{
			Value: yValues[i],
			Label: xValues[i],
			Style: chart.Style{
				StrokeWidth: 1,
				StrokeColor: r.colors[i%len(r.colors)],
				FillColor:   r.colors[i%len(r.colors)],
				FontSize:    10,
				FontColor:   drawing.Color{R: 0, G: 0, B: 0, A: 255},
			},
		}
	}

	graph := chart.BarChart{
		Title: title,
		Background: chart.Style{
			Padding: chart.Box{
				Top:    20,
				Left:   20,
				Right:  20,
				Bottom: 20,
			},
			FillColor: drawing.Color{R: 255, G: 255, B: 255, A: 255},
		},
		Height:   400,
		BarWidth: 60,
		Bars:     bars,
		XAxis: chart.Style{
			StrokeWidth: 1,
			StrokeColor: drawing.Color{R: 0, G: 0, B: 0, A: 255},
		},
		YAxis: chart.YAxis{
			Style: chart.Style{
				StrokeWidth: 1,
				StrokeColor: drawing.Color{R: 0, G: 0, B: 0, A: 255},
			},
		},
	}

	// 保存图表
	return r.saveChart(&graph, outputPath)
}

// RenderScatterChart 渲染散点图
func (r *ChartRenderer) RenderScatterChart(title string, xLabel string, yLabel string, xValues []float64, yValues []float64, outputPath string) error {
	// 检查数据范围是否为零
	xAllZero := true
	yAllZero := true

	for _, v := range xValues {
		if v > 0 {
			xAllZero = false
			break
		}
	}

	for _, v := range yValues {
		if v > 0 {
			yAllZero = false
			break
		}
	}

	// 如果所有值都是零，添加一个小的偏移量以避免数据范围为零
	if xAllZero && len(xValues) > 0 {
		for i := range xValues {
			xValues[i] = 0.1 // 添加一个小的非零值
		}
	}

	if yAllZero && len(yValues) > 0 {
		for i := range yValues {
			yValues[i] = 0.1 // 添加一个小的非零值
		}
	}

	series := chart.ContinuousSeries{
		XValues: xValues,
		YValues: yValues,
		Style: chart.Style{
			StrokeWidth: 1,
			StrokeColor: r.colors[0],
			FillColor:   r.colors[0],
			FontSize:    10,
			FontColor:   drawing.Color{R: 0, G: 0, B: 0, A: 255},
		},
	}

	graph := chart.Chart{
		Title: title,
		TitleStyle: chart.Style{
			FontSize:  14,
			FontColor: drawing.Color{R: 0, G: 0, B: 0, A: 255},
		},
		Width:  800,
		Height: 400,
		Series: []chart.Series{series},
		Background: chart.Style{
			Padding: chart.Box{
				Top:    20,
				Left:   20,
				Right:  20,
				Bottom: 20,
			},
			FillColor: drawing.Color{R: 255, G: 255, B: 255, A: 255},
		},
		Canvas: chart.Style{
			FillColor: drawing.Color{R: 255, G: 255, B: 255, A: 255},
		},
		XAxis: chart.XAxis{
			Name: xLabel,
			Style: chart.Style{
				StrokeWidth: 1,
				StrokeColor: drawing.Color{R: 0, G: 0, B: 0, A: 255},
			},
		},
		YAxis: chart.YAxis{
			Name: yLabel,
			Style: chart.Style{
				StrokeWidth: 1,
				StrokeColor: drawing.Color{R: 0, G: 0, B: 0, A: 255},
			},
		},
	}

	// 保存图表
	return r.saveChart(&graph, outputPath)
}

// RenderTimeSeriesChart 渲染时间序列图
func (r *ChartRenderer) RenderTimeSeriesChart(title string, xLabel string, yLabel string, times []time.Time, seriesData [][]float64, seriesNames []string, outputPath string) error {
	// 检查数据范围是否为零
	for i, data := range seriesData {
		allZero := true
		for _, v := range data {
			if v > 0 {
				allZero = false
				break
			}
		}

		// 如果所有值都是零，添加一个小的偏移量以避免数据范围为零
		if allZero && len(data) > 0 {
			for j := range data {
				seriesData[i][j] = 0.1 // 添加一个小的非零值
			}
		}
	}

	series := make([]chart.Series, len(seriesData))
	for i, data := range seriesData {
		series[i] = chart.TimeSeries{
			Name:    seriesNames[i],
			XValues: times,
			YValues: data,
			Style: chart.Style{
				StrokeWidth: 1,
				StrokeColor: r.colors[i%len(r.colors)],
				FillColor:   r.colors[i%len(r.colors)],
				FontSize:    10,
				FontColor:   drawing.Color{R: 0, G: 0, B: 0, A: 255},
			},
		}
	}

	graph := chart.Chart{
		Title: title,
		TitleStyle: chart.Style{
			FontSize:  14,
			FontColor: drawing.Color{R: 0, G: 0, B: 0, A: 255},
		},
		Width:  800,
		Height: 400,
		Series: series,
		Background: chart.Style{
			Padding: chart.Box{
				Top:    20,
				Left:   20,
				Right:  20,
				Bottom: 20,
			},
			FillColor: drawing.Color{R: 255, G: 255, B: 255, A: 255},
		},
		Canvas: chart.Style{
			FillColor: drawing.Color{R: 255, G: 255, B: 255, A: 255},
		},
		XAxis: chart.XAxis{
			Name: xLabel,
			Style: chart.Style{
				StrokeWidth: 1,
				StrokeColor: drawing.Color{R: 0, G: 0, B: 0, A: 255},
			},
		},
		YAxis: chart.YAxis{
			Name: yLabel,
			Style: chart.Style{
				StrokeWidth: 1,
				StrokeColor: drawing.Color{R: 0, G: 0, B: 0, A: 255},
			},
		},
	}

	// 保存图表
	return r.saveChart(&graph, outputPath)
}
